#!/usr/bin/perl
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 2002,2004 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 

use strict;
use POSIX qw(strftime);      # This is to format the time correctly


#/******************************************************************/
# local and global variables
#/******************************************************************/

$::severity = 0;             # we initialize severity to 0, meaning its "info" not an error.
$::SYSTIME  = 0;
my ($host, $ip,$line,$oid,$val,$msg,$trapOID,$rc);    # local variables
my %ERRM = ( "errmCondSeverity"   => "",   # hash with errm values
 	     "errmType"           => "",   # that will be passed in
	     "errmCondName"       => "",   # if this is an errmEvent
	     "errmNodeName"       => "",   # trap.
             "errmRsrcName"       => "",
             "errmRsrcClassName"  => "",
             "errmAttrName"       => "",
             "errmDataType"       => "",
             "errmValue"          => "",
             #"errmMessage"        => ""
            );

#/******************************************************************/
# function: processMsg will format a message to be sent to the 
# AuditLog and SNMPTrap sensor.  It will take in one arg: The message 
# that will be sent. Then it will add the message to the audit log and 
# send the message to SNMPTrap sensor.  It will return the return code 
# of the calls. 
#/******************************************************************/

sub processMsg{
    my $msg = shift;
#	$msg =~ s/"//g;
    if($::ERRMEVENT){
	

    }
    # my $resourceHandle =
    chomp(my $hostname = `/bin/hostname`);
    my $cmd =  "/usr/sbin/rsct/bin/runact-api ";  # build runact-api command 
    $cmd .= "-o IBM.AuditLog::SNMP"; # run this on the IBM.AuditLog resource class
    $cmd .= "::$hostname";     # run this on the local host 
    $cmd .= "::AddRecord";     # the action is to add a record
    $cmd .= "::Time::$::SYSTIME";       # Give this a valid time
    $cmd .= "::Category::$::severity";  # how severe is it?
    $cmd .= "::TemplateId::0";          # SNMP templatae id is 0
    $cmd .= "::SourceNode::$hostname";             # append the hostname
    $cmd .= "::'(CT_CHAR_PTR)'::\"$msg\"";         # append the message
    my $rc = system("$cmd");                       # execute command
    $rc = $rc >> 8;                                # get the return code

    $cmd = "/usr/sbin/rsct/bin/runact-api ";  # build runact-api command
    $cmd .= "-o IBM.Sensor::SNMPTrap"; # run this on IBM.Sensor resource class
    $cmd .= "::$hostname";  # run this on the local host
    $cmd .= "::SetValues";  # the action is set value
    $cmd .= "::FieldIndicator::1"; # set one value
    $cmd .= "::String::\"$msg\"";  # set value String to $msg
    my $rc2 = system("$cmd");  # execute command
    $rc2 = $rc2 >> 8;  # get the return code

    $rc &= $rc2;  # combine the return codes from two calls.
    return $rc;  # return the exit value

}



sub lineParser {
	# This program supports ucd-snmp and net-snmp packages and SNMP version 
	# 2c trap.
	#
	# The the snmptrapd in the net-snmp and ucd-snmp send SNMP trap message
	# to STDIN in deferent text format.
	# e.g. if you use the 
	# snmptrap -v 2c -c public localhost '' 0 0 s "hello, is me"
	# command to generate an SNMP trap in both system,
	#
	# in the ucd-snmp system, you got:
	# localhost.localdomain
	# 127.0.0.1
	# system.sysUpTime.0 21:17:25:41.36
	# .iso.org.dod.internet.snmpV2.snmpModules.snmpMIB.snmpMIBObjects.snmpTrap.snmpTrapOID.0 0
	# 0 "hello, is me"
	#
	# in the net-snmp sytem you got:
	# localhost.localdomain
	# 127.0.0.1
	# SNMPv2-MIB::sysUpTime.0 9:16:32:50.04
	# SNMPv2-MIB::snmpTrapOID.0 SNMPv2-SMI::zeroDotZero
	# SNMPv2-SMI::zeroDotZero "hello, is me"
	#
	# This function is use to parse the lines after line 2 for both
	# ucd-snmp and net-snmp.


	my $msg = shift;
	chomp($msg);
	my ($a, $b) = split (/\s+/, $msg, 2);

	# takes out the net-snmp specific text from the texts
	$a =~ s/^SNMPv2\S+\:\://;
	$b =~ s/^SNMPv2\S+\:\://;

	# take of the '"' in front of and in the end message. substitute the 
	# ':' to '\:' to avoid the exsistance of '::' in the message. notice
	# that '::' is used as field seperator in runact-api.
	$a =~ s/^"//;
	$a =~ s/"$//;
	$a =~ s/:/\\:/g; 
	$b =~ s/^"//;
	$b =~ s/"$//;
	$b =~ s/:/\\:/g; 
	return ($a, $b);
}


#/******************************************************************/
#
# MAIN -- Start of program
#
#/******************************************************************/

if($::ARGV[0] eq "errmEvent"){  # check if this is an errmEvent trap
    $::ERRMEVENT="true";        # if this is an errmevent flag it.
}


# The host and ip address are passed in by snmptrapd via
# STDIN.  These are the first arguments of any trap.



chomp($host = <STDIN>);      # line 1: get host name
chomp($ip   = <STDIN>);      # line 2: get ip address


# Get the Time value set to local time.

$line = <STDIN>;         # line 3: we don't do anything with this value now.

$::SYSTIME = strftime("%s", localtime());  # get the local time.
$::SYSTIME .= "000000"; # multiply seconds to make microseconds.



# The next line received is always the trap id.
# This will tell what type of trap has been received.

$line = <STDIN>;         # line 4: read the line from STDIN
($oid,$val) = lineParser($line);  

# todo: We only support SNMP version 2 traps this is a place
# we can check for that.  We can see if this is an snmp 
# trap by seeing that the OID is:
# .iso.org.dod.internet.snmpV2.snmpModules.snmpMIB.snmpMIBObjects.snmpTrap.snmpTrapOID.0

$trapOID = $val;

# todo: We should also check that if $::ERRMEVENT is set then 
# this trapOID is:
# enterprises.ibm.ibmProd.ibmRSCT.rsctNotifications.errmEvent

if($::ERRMEVENT){


    # make sure that this trap did not come from the localhost:
    # get all the possible local ip addresses:
    my $cmd = "/sbin/ifconfig | /bin/grep inet | /bin/awk '{print \$2}'";
    chomp(my @inets = `$cmd`);
    if($? >> 8){
	print "ERROR RUNNING: $cmd";
	exit 1;
    }

    # push and split ips out of the line.  Then put them in the @ip array.
    my @ips;
    foreach(@inets){
	push @ips, (split(':', $_))[1]; 
    }
    foreach(@ips){
	if($ip eq $_){
	    #print "$ip is equal to $_.\n";
	    exit 0;              # exit if this came from ourselves.
        }
    }
    
 
    while(($line = <STDIN>)){              # read a line of stdin
       	($oid, $val) = lineParser($line);  # Separate the line into OID and value
	my @oidParts;
        # find if ucd-snmp is in the rpm table
        $cmd = "/bin/rpm -qa | grep net-snmp > /dev/null";   
	system("$cmd");
 	if($? >> 8){
            # the installed snmp is not net-snmp
            @oidParts = split /\./,$oid; 
 	}else {
            # it is net-snmp 
            @oidParts = split /::/,$oid;
 	}

	my $varBind = $oidParts[$#oidParts]; # The last part is the varbind
	my $match = 0;
	foreach(keys %ERRM){               # make sure that each varbind received
	    if($varBind eq $_){            # is a value in the ERRM hash table.
		$match = "true";
		$ERRM{$_} = $val;
	        last;
 	    }
	}
	unless($match){                    # if there was no match, then we exit.
	  exit 1;
  	}        
    }

    # We need to check that all the variables were
    # defined in the hash:
    foreach (keys %ERRM){
	if($ERRM{$_}){
	  print "$_ is defined as: $ERRM{$_}\n";
  	}else{
	  print "$_ is not defined : $ERRM{$_}\n";
	  exit 1;  # just exit, if not all the variables
		   # were defined, then we just forgetaboutit.

	}
    }
    
    # if the severity is severe, we should make that
    # known:
    if($ERRM{"errmCondSeverity"} eq "Critical"){
	$::severity = 1;
    }
	 
    # get the message that will go to the 
    # auditlog ready

    $msg = "ERRM Trap from $host ($ip)"; # print to AuditLog
    $msg .= "severity: $ERRM{errmCondSeverity}\n";
    $msg .= "type:  $ERRM{errmType}\n";	
    $msg .= "condition: $ERRM{errmCondName}\n";
    $msg .= "resource: $ERRM{errmRsrcName}\n";
    $msg .= "resource class: $ERRM{errmRsrcClassName}\n";
    $msg .= "node: $ERRM{errmNodeName}";
   
    $rc = &processMsg($msg);


}else{  # This command is for all other SNMP traps received.


    $msg = "SNMP Trap from $host ($ip)\n"; # print to AuditLog
    $msg .= "Trap Type: $trapOID\n";
    # The other OID's are left to be fed in from snmptrapd via
    # STDIN.  We take all of these and put them in the AuditLog

    while(($line = <STDIN>)){
    	($oid, $val) = lineParser($line);
    	$msg .= "OID: $oid VALUE: $val\n";
    }

    $rc = &processMsg($msg);
}


exit $rc;
